/*
 * @features: 功能
 * @description: 说明
 * @Date: 2020-12-27 19:03:36
 * @Author: judu233(769471424@qq.com)
 * @LastEditTime: 2021-02-10 22:41:05
 * @LastEditors: judu233
 */

const { ccclass, property } = cc._decorator;

enum E_PieceMaskType {
    ancho = `ancho`,
    bordA = `bordA`,
    bordB = `bordB`,
    centerA = `centerA`,
    centerB = `centerB`,
}
enum E_PiecePosType {
    left_up = `left_up`,
    right_up = `right_up`,
    right_down = `right_down`,
    left_down = `left_down`,
    up = `up`,
    right = `right`,
    down = `down`,
    left = `left`,
    center = `center`,
}
const MASK_TYPE = `maskType`;

@ccclass
export default class NewClass extends cc.Component {

    /**角落mask */
    @property(cc.SpriteFrame)
    private anchoMask: cc.SpriteFrame = null;

    /**边缘mask */
    @property(cc.SpriteFrame)
    private borderMaskA: cc.SpriteFrame = null;
    @property(cc.SpriteFrame)
    private borderMaskB: cc.SpriteFrame = null;

    /**中心Mask */
    @property(cc.SpriteFrame)
    private centerMask: cc.SpriteFrame = null;

    @property(cc.Node)
    private contentNode: cc.Node = null;

    @property(cc.SpriteFrame)
    private contentSf: cc.SpriteFrame = null;

    /**碎片的倍数--1x1为4x4, 2x2=6x6 3x3=8x8 */
    multipleSize = cc.size(2, 2);

    /**格子的行数和列数 */
    private gradCount: cc.Size;
    /**拼图容器的大小 */
    private bgSize = cc.size(500, 500);
    /**每个格子实际大小 */
    private cellSize: cc.Size;

    /**碎片去掉凸出部分的宽高的方形原始尺寸 */
    private pieceSize: number;
    /**碎片偏移尺寸 */
    private pieceOffset: number;

    /**碎片map */
    private pieceMap: Map<string, cc.Node> = new Map();

    @property(cc.Node)
    t: cc.Node = null;

    start() {
        this.generatePiece();
    }

    generatePiece() {
        this.gradCount = cc.size(this.multipleSize.width * 2 + 2, this.multipleSize.height * 2 + 2);
        this.cellSize = cc.size(this.bgSize.width / this.gradCount.width, this.bgSize.height / this.gradCount.height);
        let anchoSize = this.anchoMask.getOriginalSize();
        this.pieceSize = Math.min(anchoSize.width, anchoSize.height);
        this.pieceOffset = (Math.max(anchoSize.width, anchoSize.height) - this.pieceSize);

        for (let i = 0; i < this.gradCount.width; i++) {
            for (let j = 0; j < this.gradCount.height; j++) {
                //初始位置
                let startPos = cc.v2(
                    this.pieceSize * j,
                    -(this.pieceSize * i),
                );
                let { maskSf, pieceType, pos, rotation, offset } = this.getMask(i, j);

                // if (pos == E_PiecePosType.left || pos == E_PiecePosType.right) continue;
                if (pos != E_PiecePosType.center) continue;
                let pieceNode = this.createPiece(maskSf, pieceType, rotation, startPos, offset);
                this.contentNode.addChild(pieceNode);
            }
        }
        this.contentNode.scale = 0.5;
    }

    getMask(i: number, j: number) {
        let isLeftUp = (i == 0 && j == 0);
        let isRightUp = (i == 0 && j == this.gradCount.width - 1);
        let isLeftDown = (j == 0 && i == this.gradCount.height - 1);
        let isRightDown = (j == this.gradCount.width - 1 && i == this.gradCount.height - 1);
        let isLeft = (i > 0 && i < this.gradCount.height - 1 && j == 0);
        let isUp = (j > 0 && j < this.gradCount.width - 1 && i == 0);
        let isRight = (i > 0 && i < this.gradCount.height - 1 && j == this.gradCount.width - 1);
        let isDown = (j > 0 && j < this.gradCount.width - 1 && i == this.gradCount.height - 1);
        let rowIsModeA = i % 2 != 0;
        let colIsModeA = j % 2 != 0;
        let pieceType = E_PieceMaskType.ancho, maskSf = this.anchoMask,
            pos: E_PiecePosType, rotation: number, offset: cc.Vec2, offsetCoefficient = 1;
        let maskSize = maskSf.getOriginalSize();
        //4个角
        if (isLeftUp) {
            pos = E_PiecePosType.left_up;
            rotation = 0;
        } else if (isLeftDown) {
            pos = E_PiecePosType.left_down;
            rotation = 270;
            offset = cc.v2(0, -maskSize.height + this.pieceOffset * offsetCoefficient);
        } else if (isRightUp) {
            pos = E_PiecePosType.right_up;
            rotation = 90;
            offset = cc.v2(maskSize.width, 0);
        } else if (isRightDown) {
            pos = E_PiecePosType.right_down;
            offset = cc.v2(maskSize.width, -maskSize.height + this.pieceOffset * offsetCoefficient);
            rotation = 180;
        } else if (isLeft || isRight) {
            rotation = isLeft ? 270 : 90;
            pieceType = !(isLeft ? rowIsModeA : !rowIsModeA) ? E_PieceMaskType.bordA : E_PieceMaskType.bordB;
            maskSf = !(isLeft ? rowIsModeA : !rowIsModeA) ? this.borderMaskA : this.borderMaskB;
            offsetCoefficient = rowIsModeA ? offsetCoefficient : 0;
            if (isLeft) {
                offset = rowIsModeA ?
                    cc.v2(0, -maskSize.height + this.pieceOffset * offsetCoefficient) :
                    cc.v2(0, -maskSize.height - this.pieceOffset * offsetCoefficient);
            } else {
                offset = !rowIsModeA ?
                    cc.v2(maskSize.width, this.pieceOffset * offsetCoefficient) :
                    cc.v2(maskSize.width, this.pieceOffset * offsetCoefficient);
            }
            pos = isLeft ? E_PiecePosType.left : E_PiecePosType.right;
        } else if (isUp || isDown) {
            rotation = isUp ? 0 : 180;
            pieceType = (isUp ? colIsModeA : !colIsModeA) ? E_PieceMaskType.bordA : E_PieceMaskType.bordB;
            if (isUp) {
                offset = colIsModeA ?
                    cc.v2(-this.pieceOffset * offsetCoefficient, 0) :
                    cc.v2(-this.pieceOffset * (offsetCoefficient - 1), 0);
            } else {
                offset = !colIsModeA ?
                    cc.v2(maskSize.width + this.pieceOffset * offsetCoefficient, -maskSize.height + this.pieceOffset * offsetCoefficient) :
                    cc.v2(maskSize.width + this.pieceOffset * (offsetCoefficient - 1), -maskSize.height + this.pieceOffset * offsetCoefficient);
            }
            maskSf = (isUp ? colIsModeA : !colIsModeA) ? this.borderMaskA : this.borderMaskB;
            pos = isUp ? E_PiecePosType.up : E_PiecePosType.down;
        } else {
            if ((colIsModeA && !rowIsModeA) || (!colIsModeA && rowIsModeA)) {
                rotation = 90;
                pieceType = E_PieceMaskType.centerA;
                offset = cc.v2(maskSize.width + this.pieceOffset * offsetCoefficient, this.pieceOffset * (offsetCoefficient - 1));
            } else {
                rotation = 0;
                pieceType = E_PieceMaskType.centerB;
                offset = cc.v2(0, this.pieceOffset * offsetCoefficient);
            }
            maskSf = this.centerMask;
            pos = E_PiecePosType.center;
        }
        return { pieceType, maskSf, pos, rotation, offset };
    }

    createPiece(maskSf: cc.SpriteFrame, pieceType: E_PieceMaskType, rotation: number, startPos: cc.Vec2, offset: cc.Vec2) {
        let mask = new cc.Node().addComponent(cc.Mask);
        let bg = new cc.Node().addComponent(cc.Sprite);

        bg.node.setAnchorPoint(cc.v2(0, 1));
        bg.spriteFrame = this.contentSf;
        mask.type = cc.Mask.Type.IMAGE_STENCIL;
        mask.spriteFrame = maskSf;
        mask.alphaThreshold = 0.01;

        //设置节点
        mask.node.addChild(bg.node);
        mask.node.setAnchorPoint(cc.v2(0, 1));
        mask.node.scale = 1;
        mask.node.angle = -rotation;
        mask.node[MASK_TYPE] = pieceType;
        // startPos = startPos.divide(4);
        if (offset)
            startPos.addSelf(offset);
        mask.node.setPosition(startPos);

        let maskSize = maskSf.getOriginalSize();
        mask.node.setContentSize(maskSize);

        mask.node.addChild(cc.instantiate(this.t));
        this.t.setPosition(cc.v2(0, 0));

        return mask.node;
    }

    // update (dt) {}
}
